package com.tangruojie.stream;

import com.tangruojie.entity.Author;
import com.tangruojie.entity.Book;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Predicate;

/**
 * Stream 的技术优势总结
 * 1. 🧱 函数式编程：声明式处理数据
 * 不需要临时变量
 * 支持 Lambda 表达式，逻辑更集中
 * 2. 🔗 链式操作：自然的流水线编程风格
 * 支持 .filter(), .map(), .sorted(), .limit() 等方法链
 * 更符合数据“从源头到结果”的处理方式
 * 3. 🧠 延迟执行（Lazy Evaluation）
 * 调用 .filter() 等中间操作不会立即执行
 * 只有 .collect()、.forEach() 等终结操作调用时才触发执行，提高效率
 * 4. ⚡ 支持并行处理（ParallelStream）
 * 使用 .parallelStream() 可以多线程加速数据处理
 * 对大数据量集合有显著性能提升
 * 5. 🔁 简化复杂处理逻辑
 * 如：
 * 去重 .distinct()
 * 排序 .sorted(Comparator)
 * 分组 .collect(Collectors.groupingBy(...))
 * 聚合 .max(), .min(), .count()
 */
public class StreamDemoTest {

    public static List<Author> getAuthors() {
        // 数据初始化
        Author author1 = new Author(1L, "墨香", 33, "一个从双力中撕扯重组的世界人", null);
        Author author2 = new Author(2L, "灵兮", 15, "耳环挂在下垂的眼角", null);
        Author author3 = new Author(3L, "GL", 14, "这个世界只能倒转的星群", null);
        Author author4 = new Author(3L, "GL", 14, "这个世界只能倒转的星群", null);

        // 构造书籍列表
        List<Book> books1 = new ArrayList<>();
        List<Book> books2 = new ArrayList<>();
        List<Book> books3 = new ArrayList<>();

        books1.add(new Book(1L, "刀剑的世界里能更好与世界对话", "哲学，道德", 88, "用一起切刀了解世界"));
        books1.add(new Book(2L, "一个人不能死在一把刀下", "个体成长，人性", 99, "锋利的规则从来就不属于我"));

        books2.add(new Book(3L, "黑水的河流", "数学，小说", 85, "带骨用母亲生数的世界"));
        books2.add(new Book(3L, "黑水的河流", "数学，小说", 85, "带骨用母亲生数的世界"));
        books2.add(new Book(4L, "腐蚀的果皮", "心理，人文", 85, "你就是神对腐烂的回应"));

        books3.add(new Book(5L, "时间的沙堆是我的骨骼", "文学", 56, "无法想象一个存在被他们看做自闭症"));
        books3.add(new Book(6L, "从身体下车", "人伦，道德", 100, "两个骨节交叉就构成你要怎么构成的权威"));
        books3.add(new Book(6L, "从身体下车", "人伦，道德", 100, "两个骨节交叉就构成你要怎么构成的权威"));

        // 绑定书籍到作者
        author1.setBooks(books1);
        author2.setBooks(books2);
        author3.setBooks(books3);
        author4.setBooks(books3); // 第四个作者和第三个共用一组书籍

        // 返回列表
        return new ArrayList<>(Arrays.asList(author1, author2, author3, author4));
    }

    /**
     * Stream 三步走核心流程
     * 1. 获取数据源 → stream()
     * 2. 进行中间操作 → filter, map, sorted 等
     * 3. 执行终结操作 → collect, forEach, reduce 等
     */
    /**
     * Stream 适用的典型场景
     * 场景	        方法
     * 筛选	        .filter()
     * 转换	        .map()
     * 扁平化	    .flatMap()
     * 去重	        .distinct()
     * 排序	        .sorted()
     * 截取	        .limit(), .skip()
     * 统计	        .count(), .max(), .min()
     * 收集	        .collect(Collectors.toList()) 等
     */
    /**
     * Stream 和 Lambda 的关系
     * Stream 是一种数据流式处理工具
     * Lambda 是简洁地传入操作逻辑（参数→返回值）
     */
    public static void main(String[] args) {
        List<Author> authors = getAuthors();
        authors.stream() // 将集合转化为流
                .distinct() // 去重
                .filter(new Predicate<Author>() {
                    @Override
                    public boolean test(Author author) {
                        return author.getAge() < 18;
                    }
                }) // 过滤
                .forEach(new Consumer<Author>() {
                    @Override
                    public void accept(Author author) {
                        System.out.println(author.getName());
                    }
                }); // 遍历
        authors.stream() // 将集合转化为流
                .distinct() // 去重
                .filter(author -> author.getAge() < 18) // 过滤
                .forEach(author -> System.out.println(author.getName())); // 遍历
    }

}
/**
 * 编号	    注意事项	                    建议
 * 1️⃣	    Stream 只能用一次	            每次重新获取
 * 2️⃣	    惰性执行	                    终止操作才触发
 * 3️⃣	    不要修改原集合	                使用 collect
 * 4️⃣	    避免副作用	                不推荐外部变量
 * 5️⃣	    map vs flatMap 区分	        数据结构不同时需转换
 * 6️⃣	    调试用 peek()	            替代 forEach
 * 7️⃣	    并行流要谨慎	                适合 CPU 密集场景
 * 8️⃣	    null 安全问题	            加 Optional 判断
 * 9️⃣	    操作链太长难读	                建议拆分
 * 🔟	    不要在 stream 中执行 IO 操作	分离逻辑和副作用
 */